﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace MAF.Common
{
    /// <summary>
    /// 反射帮助类
    /// </summary>
    public class ReflectHelper
    {
        /// <summary>
        /// 设置字段/属性值
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="fieldName"></param>
        /// <param name="newValue"></param>
        public static void SetMemberValue(object instance, string fieldName, object newValue)
        {
            Type t = instance.GetType();
            try
            {
                t.InvokeMember(fieldName, BindingFlags.SetField | BindingFlags.SetProperty, null, instance, new object[] { newValue });
            }
            catch { }
        }

        /// <summary>
        /// 读取字段/属性值
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="fieldName"></param>
        public static T GetMemberValue<T>(object instance, string fieldName)
        {
            var obj = GetMemberValue(instance, fieldName);
            return (null == obj) ? default(T) : (T)obj;
        }

        /// <summary>
        /// 读取字段/属性值
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="fieldName"></param>
        /// <returns>如果fieldName没有找到，也会返回null</returns>
        public static object GetMemberValue(object instance, string fieldName)
        {
            Type t = instance.GetType();
            try
            {
                return t.InvokeMember(fieldName, BindingFlags.GetField | BindingFlags.GetProperty, null, instance, null);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 是否存在某字段/属性
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static bool IsExistsMember(Type type, string name)
        {
            // 先搜索属性
            PropertyInfo prop = type.GetProperty(name);
            if (null != prop)
                return true;

            FieldInfo field = type.GetField(name);
            if (null != field)
                return true;

            return false;
        }

        /// <summary>
        /// 深度克隆对象，被克隆对象必须可序列化
        /// </summary>
        /// <param name="obj">要克隆的对象(该对象需可序列化)</param>
        /// <returns>克隆所得新对象</returns>
        public static T DeepClone<T>(T obj)
        {
            using (var stream = new MemoryStream())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
                stream.Position = 0;
                var newObj = (T)formatter.Deserialize(stream);
                return newObj;
            }
        }
    }
}
